<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
  function sleep(delay){
    console.log('sleep~~~~~');
    for (let t = Date.now(); Date.now() - t <= delay;) {}
  }

  //rootFiber start ---
  //#region
  const A1 = {type: 'div', key: 'A1'};
  const B1 = {type: 'div', key: 'B1', return: A1};
  const B2 = {type: 'div', key: 'B2', return: A1};
  const C1 = {type: 'div', key: 'C1', return: B1};
  const C2 = {type: 'div', key: 'C2', return: B1};

  A1.child = B1;
  B1.sibling = B2;
  B1.child = C1;
  C1.sibling = C2;
  //#endregion
  //--- rootFiber end

  const rootFiber = A1;
  let nextUnitOfWork = null;

  function workLoop(deadline){
    console.log('~~~~~~~~~~新的一帧~~~~~~~~~');
    while ((deadline.timeRemaining() > 0 || deadline.didTimeout) && nextUnitOfWork) {
      nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
    }

    if(!nextUnitOfWork){
      console.log('render阶段结束了');
    }else{
      window.requestIdleCallback(workLoop, {timeout: 1000});
    }
  }

  function performUnitOfWork(fiber) {
    console.log('performUnitOfWork');
    beginWork(fiber); // 处理此fiber
    if(fiber.child){ // 如果有儿子 则返回大儿子
      console.log('返回子节点:',fiber.child);
      return fiber.child;
    }
    while (fiber){
      /*
        第一次进来:
          打印C1结束->通过C1找到C2并返回
        第二次进来:
          C2没有儿子 打印C2结婚时-> C2也没有兄弟 -> fiber = fiber.return fiber赋了新值B1,fiber有值,继续while循环
          -> 打印B1完成 -> B1找到自己的下个兄弟节点B2并返回
      */
      completeUnitOfWork(fiber); // C1 节点没有孩子 直接完成 开始遍历下一个节点 看有没有兄弟节点 有则返回兄弟节点 无则返回上级节点 // C2
      if (fiber.sibling) { // C2
        console.log('返回下一个兄弟节点:',fiber.sibling);
        return fiber.sibling; // 如果说有弟弟 返回 弟弟
      }
      console.log('返回上级节点:',fiber.return);
      fiber = fiber.return; //
    }
  }

  function beginWork(fiber){
    sleep(20);
    console.log('开始 fiber.key:',fiber.key);
  }

  function completeUnitOfWork(fiber){
    console.log('结束 fiber.key:',fiber.key);
  }

  nextUnitOfWork = rootFiber;

  window.requestIdleCallback(workLoop,{timeout: 1000});

</script>
</body>
</html>
